package org.ruizhijie.run;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.ruizhijie.config.SystemConfig;
import org.ruizhijie.config.TopicQueue;
import org.ruizhijie.i.impl.OutTcpSubcriberImpl;
import org.ruizhijie.run.tcp.ServerChannelInitializer;

public class TcpServer {
	private Logger log = LogManager.getLogger(LogManager.ROOT_LOGGER_NAME);
	// 处理Accept连接事件的线程，这里线程数设置为1即可，netty处理链接事件默认为单线程，过度设置反而浪费cpu资源
	private final EventLoopGroup bossGroup = new NioEventLoopGroup(1);
	// 处理hadnler的工作线程，其实也就是处理IO读写 。线程数据默认为 CPU 核心数乘以2
	private final EventLoopGroup workerGroup = new NioEventLoopGroup(2);
	private static Map<String, Channel> map = new ConcurrentHashMap<String, Channel>();

	public TcpServer(TopicQueue tq,String topic) {
		try {
			// 创建ServerBootstrap实例
			ServerBootstrap serverBootstrap = new ServerBootstrap();
			// 初始化ServerBootstrap的线程组
			serverBootstrap.group(bossGroup, workerGroup);
			// 设置将要被实例化的ServerChannel类
			serverBootstrap.channel(NioServerSocketChannel.class);
			// 在ServerChannelInitializer中初始化ChannelPipeline责任链，并添加到serverBootstrap中
			serverBootstrap.childHandler(new ServerChannelInitializer());
			// 标识当服务器请求处理线程全满时，用于临时存放已完成三次握手的请求的队列的最大长度
			serverBootstrap.option(ChannelOption.SO_BACKLOG, 1024);
			// 是否启用心跳保活机机制
			serverBootstrap.childOption(ChannelOption.SO_KEEPALIVE, true);
			// 绑定端口后，开启监听
			ChannelFuture channelFuture = serverBootstrap.bind(SystemConfig.tcpServerPort).sync();
			if (channelFuture.isSuccess()) {
				log.info("TCP服务启动 成功---------------");
			}
			
			new OutTcpSubcriberImpl(tq, topic, map);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public static Map<String, Channel> getMap() {
		return map;
	}
}
